#include <NativeExecutive/CExecutiveManager.h>

#include <thread>
#include <chrono>

using namespace std::chrono;

using namespace NativeExecutive;

static void test_condition_variable( CExecutiveManager *nativeMan )
{
    // We need a condition variable.
    CCondVar *condVar = nativeMan->CreateConditionVariable();

    // Create a test lock for condition contexts.
    CReadWriteLock *condLock = nativeMan->CreateReadWriteLock();

    // Test that we can wait on a condition from another thread.
    printf( "testing conditional variable basic wait..." );
    {
        CExecThread *secondThread = CreateThreadL( nativeMan,
            [&]( CExecThread *thread )
        {
            CReadWriteWriteContextSafe <> ctxLock( condLock );
            condVar->Wait( ctxLock );
        });

        secondThread->Resume();

        std::this_thread::sleep_for( 1000ms );

        // Now signal the thread.
        condVar->Signal();

        // This should not wait indefinately.
        nativeMan->JoinThread( secondThread );

        // Get rid of our thread.
        nativeMan->CloseThread( secondThread );
    }
    printf( "ok.\n" );

    // Now test if we can terminate a thread that is waiting on a condVar.
    printf( "testing conditional variable termination during wait..." );
    {
        CReadWriteWriteContextSafe <> ctxLock( condLock );

        CExecThread *secondThread = CreateThreadL( nativeMan,
            [&]( CExecThread *thread )
        {
            condVar->Wait( ctxLock );
        });

        secondThread->Resume();

        // Wait a little.
        std::this_thread::sleep_for( 100ms );

        // Get rid of our thread.
        secondThread->Terminate();

        nativeMan->CloseThread( secondThread );
    }
    printf( "ok.\n" );

    // Now lets perform a more advanced scenario test where multiple threads will wait on a conditional variable
    // but we will only terminate a few of those.
    printf( "testing conditional variable multi-thread wait termination..." );
    {
        //TODO.
    }
    printf( "ok.\n" );

    nativeMan->CloseReadWriteLock( condLock );

    nativeMan->CloseConditionVariable( condVar );

    // OK.
}

int main( int argc, char *argv[] )
{
    CExecutiveManager *nativeMan = CExecutiveManager::Create();

    assert( nativeMan != NULL );

    // Test 1: Condition variables.
    test_condition_variable( nativeMan );

    CExecutiveManager::Delete( nativeMan );
}